/**
 * Project Name:TypedMeatballMatcher.java
 * File Name:TypedMeatballMatcher.java
 * Date:2019/4/8 9:32
 * Copyright (c) 2019, zhang.xiangyu@foxmail.com All Rights Reserved.
 */
package com.meatball.base.repository.matcher;

import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import lombok.experimental.Wither;
import lombok.extern.log4j.Log4j2;
import org.springframework.util.Assert;

import java.util.*;

/**   
 * @Title: TypedMeatballMatcher.java
 * @Description: todo() 
 * @Author: 張翔宇
 * @Date: 2019/4/8 9:49
 * @Version: V1.0   
 */
@Log4j2
@ToString
@EqualsAndHashCode
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class TypedMeatballMatcher implements MeatballMatcher {
    private final NullHandler nullHandler;
    private final StringMatcher defaultStringMatcher;
    private final PropertySpecifiers propertySpecifiers;
    private final Set<String> ignoredPaths;
    private final boolean defaultIgnoreCase;
    private  final @Wither(AccessLevel.PACKAGE)  MatchMode mode;

    TypedMeatballMatcher() {
        this(NullHandler.IGNORE, StringMatcher.DEFAULT, new PropertySpecifiers(), Collections.emptySet(), false,
                MatchMode.ALL);
    }

    @Override
    public MatchMode getMatchMode() {
        return mode;
    }

    @Override
    public PropertySpecifiers getPropertySpecifiers() {
        return propertySpecifiers;
    }

    @Override
    public MeatballMatcher withMatcher(String propertyPath, GenericPropertyMatcher genericPropertyMatcher) {
        Assert.hasText(propertyPath, "PropertyPath must not be empty(propertyath不能为空)!");
        Assert.notNull(genericPropertyMatcher, "MatcherConfigurer must not be empty(MatcherConfigurer不能是空的)!");

        PropertySpecifiers propertySpecifiers = new PropertySpecifiers(this.propertySpecifiers);
        PropertySpecifier propertySpecifier = new PropertySpecifier(propertyPath);

        if (genericPropertyMatcher.ignoreCase != null) {
            propertySpecifier = propertySpecifier.withIgnoreCase(genericPropertyMatcher.ignoreCase);
        }

        if (genericPropertyMatcher.stringMatcher != null) {
            propertySpecifier = propertySpecifier.withStringMatcher(genericPropertyMatcher.stringMatcher);
        }

        if (genericPropertyMatcher.start != null && genericPropertyMatcher.end != null) {
            propertySpecifier = propertySpecifier.withValueBettown(genericPropertyMatcher.stringMatcher,
                    genericPropertyMatcher.start, genericPropertyMatcher.end);
        }

        if (genericPropertyMatcher.parameter != null) {
            propertySpecifier = propertySpecifier.withValueIn(genericPropertyMatcher.stringMatcher, genericPropertyMatcher.parameter);
        }

        propertySpecifier = propertySpecifier.withValueTransformer(genericPropertyMatcher.valueTransformer);

        propertySpecifiers.add(propertySpecifier);
        return new TypedMeatballMatcher(nullHandler, defaultStringMatcher, propertySpecifiers, ignoredPaths,
                defaultIgnoreCase, mode);
    }

}
